Generic Migrations in Fluent Part 2

When using generic models, we had to add migrations “by hand”, something like this:


Continent<SQLiteDatabase>.defaultDatabase = .sqlite
Country<SQLiteDatabase>.defaultDatabase = .sqlite
migrations.add(migration: ContinentMigration<SQLiteDatabase>.self, database: .sqlite)
migrations.add(migration: CountryMigration<SQLiteDatabase>.self, database: .sqlite)

The above example is for .sqlite.

If we changed the database, we would have to change the specific code.

What it we could do it in a pure generic way?


Generic Migration Example

import Foundation
import Fluent

public extension MigrationConfig {
  public mutating func addVaporCountries<D>(for database: DatabaseIdentifier<D>) where D: QuerySupporting & SchemaSupporting & IndexSupporting & ReferenceSupporting {
    Continent<D>.defaultDatabase = database
    self.add(migration: ContinentMigration<D>.self, database: database)
    Country<D>.defaultDatabase = database
    self.add(migration: CountryMigration<D>.self, database: database)
  }
}

I usually put that extension to MigrationConfig in the main swift file, for example for a project named VaporCountries, I put it in VaporCountries.swift file.


Usage

In your configure.swift just add this code, with the appropriate database:


import VaporCountries
...
migrations.addVaporCountries(for: .sqlite)

Just for kicks, here’s another example, VaporSpices (another Vapor 3 package.)


import Foundation
import Fluent

public extension MigrationConfig {
  public mutating func addVaporSpices<D>(for database: DatabaseIdentifier<D>) where D: QuerySupporting & SchemaSupporting & IndexSupporting & ReferenceSupporting {
    
    Form<D>.defaultDatabase = database
    self.add(migration: FormMigration<D>.self, database: database)
    
    Heat<D>.defaultDatabase = database
    self.add(migration: HeatMigration<D>.self, database: database)
    
    Technique<D>.defaultDatabase = database
    self.add(migration: TechniqueMigration<D>.self, database: database)
    
    Season<D>.defaultDatabase = database
    self.add(migration: SeasonMigration<D>.self, database: database)
    
    Volume<D>.defaultDatabase = database
    self.add(migration: VolumeMigration<D>.self, database: database)
    
    Weight<D>.defaultDatabase = database
    self.add(migration: WeightMigration<D>.self, database: database)
    
    Type<D>.defaultDatabase = database
    self.add(migration: TypeMigration<D>.self, database: database)
    
    Function<D>.defaultDatabase = database
    self.add(migration: FunctionMigration<D>.self, database: database)
    
    Heat<D>.defaultDatabase = database
    self.add(migration: HeatMigration<D>.self, database: database)
    
    Taste<D>.defaultDatabase = database
    self.add(migration: TasteMigration<D>.self, database: database)
  }
}


SO with one-liner you can add 10 models to (any) your database


migrations.addVaporSpices(for: .sqlite)
//or
migrations.addVaporSpices(for: .psql)
//or
migrations.addVaporSpices(for: .mysql)

Prev: Generic Pre-populated Models in Fluent

Next: Making a New Vapor Package


Vapor 3 Tutorial Start




#tutorial #fluent #vapor #model #migration #db #generic #swift #pub